library(tibble)
library(readr)
library(tidyr)
library(dplyr)
library(ggplot2)
library(ggthemes)
library(purrr)
library(leaflet)
library(leaflet.extras)
library(plotly)
library(ggiraph)
library(forcats)
library(stringr)Crime Data Analysis
Crime Data Analysis
Data: https://catalog.data.gov/dataset/crime-data-from-2020-to-present
About Data: https://data.lacity.org/Public-Safety/Crime-Data-from-2020-to-Present/2nrs-mtv8/about_data
Anmerkung: Mögliche Ungenauigkeiten, da die Daten von Papier Akten übertragen wurden
OCC = Occurrence
0. Beschreibung des Datensatzes
Der Datensatz crime data from 2020 to present enthält alle Berichte über beim Los Angeles Police Department (LAPD) registrierte Vorfälle in der Stadt Los Angeles (USA) vom 01.01.2020 bis zum 14.10.2024.
Dabei sind Informationen über die Tat, wie bis zu vier Tatbestände, die verwendete Tatwaffe, Tatzeitpunkt, Tatort, sowie eine Beschreibung der Art von Umgebung angegeben. Der Tatort ist dabei laut Metadaten auf den nächsten Hunderterblock gerundet, um die Anonymität zu wahren. Über das Opfer ist dabei das Alter, das Geschlecht und die Abstammung bekannt. Wobei als Abstammung Beschreibungen wie “Weiß”, “Schwarz”, “Chinesisch” oder ähnliches verwendet wird. Zusätzlich gibt es eine Spalte für den Modus Operandi, welcher meist Details über die Straftat oder den Täter enthält.
1. Definition/Formulierung der Fragestellung
- Welche Klassen von Straftaten werden wie häufig begangen?
- Anzahl Proportional zu Schweregrad
- Viele Diebstahle & andere Straftaten um Geld zu beschaffen
- Welche Stadtteile sind besonders betroffen?
- Ärmere Stadtteile
- Stadtteile mit Gang Gebieten
- Welche Stadtteile haben besonders viele Straftaten mit Gang Einfluss?
- Kenne mich zu schlecht in LA aus
- Nicht Downtown & Beverly Hills (wohlhabendere Gegenden)
- Welche Bevölkerungsgruppe ist am meisten gefährdet? (Abhängig von Alter, Geschlecht, Abstammung)
- Junge Männer Schwarzer/Hispanischer Abstammung (weniger Wohlhaben + Gangs)
- Junge weiße Frauen bei Sexualstraftaten
- Gibt es besonders Gefährliche Arten von Orten ([Premise Desc])
- Motels, Parking Lot, Street
- Internet aka. Cyberspace
- Welche Arten von Waffen wird am meisten genutzt?
- Meistens nur unbewaffnet
- Recht viele Schusswaffen
- Wie viel Prozent haben zu Verhaftungen (und welcher Art) geführt?
- Hoffentlich über 80%
- Gibt es zeitliche Rahmen in denen mehr oder weniger Verbrechen geschehen?
- Am meisten am Abend/in der Nacht
- Anfang/Ende des Monats mehr Diebstahl/Raub? –> Gehalt auszahlung Diebstahl usw.?
- Wochenenden -> Party etc
- Sommer -> Menschen drehen bei Hitze durch
- Dunkle Jahreszeiten -> Schutz in der Dunkelheit
- Wie effektiv ist die LAPD bei der Aufklärung verschiedener Arten von Straftaten?
- Straftaten mit direktem Opfer mehr (Zeugen vorhanden)
- Welche Straftaten werden häufig am Anfang/Ende des Monats begangen?
- Gehalt auszahlung Diebstahl usw.?
- Wie hat sich die Kriminalität über die 3 Jahre verändert?
- In Corona deutlich abgenommen, ansonsten zugenommen
- Wie häufig werden welche Bevölkerungsgruppen angezeigt / vgl zu wie viele Leute welcher Bevölkerungsgruppe wohnen dort?
- Nicht in Datensatz glaube
2. Laden der Daten
rm(list = ls())
crimes.df.raw <- read_csv("Crime_Data_from_2020_to_Present.csv")
head(crimes.df.raw)# A tibble: 6 × 28
DR_NO `Date Rptd` `DATE OCC` `TIME OCC` AREA `AREA NAME` `Rpt Dist No`
<dbl> <chr> <chr> <chr> <chr> <chr> <chr>
1 190326475 03/01/2020 12… 03/01/202… 2130 07 Wilshire 0784
2 200106753 02/09/2020 12… 02/08/202… 1800 01 Central 0182
3 200320258 11/11/2020 12… 11/04/202… 1700 03 Southwest 0356
4 200907217 05/10/2023 12… 03/10/202… 2037 09 Van Nuys 0964
5 220614831 08/18/2022 12… 08/17/202… 1200 06 Hollywood 0666
6 231808869 04/04/2023 12… 12/01/202… 2300 18 Southeast 1826
# ℹ 21 more variables: `Part 1-2` <dbl>, `Crm Cd` <dbl>, `Crm Cd Desc` <chr>,
# Mocodes <chr>, `Vict Age` <dbl>, `Vict Sex` <chr>, `Vict Descent` <chr>,
# `Premis Cd` <dbl>, `Premis Desc` <chr>, `Weapon Used Cd` <dbl>,
# `Weapon Desc` <chr>, Status <chr>, `Status Desc` <chr>, `Crm Cd 1` <dbl>,
# `Crm Cd 2` <dbl>, `Crm Cd 3` <dbl>, `Crm Cd 4` <lgl>, LOCATION <chr>,
# `Cross Street` <chr>, LAT <dbl>, LON <dbl>
# Welche Typen sind enthalten?
sapply(crimes.df.raw, class) DR_NO Date Rptd DATE OCC TIME OCC AREA
"numeric" "character" "character" "character" "character"
AREA NAME Rpt Dist No Part 1-2 Crm Cd Crm Cd Desc
"character" "character" "numeric" "numeric" "character"
Mocodes Vict Age Vict Sex Vict Descent Premis Cd
"character" "numeric" "character" "character" "numeric"
Premis Desc Weapon Used Cd Weapon Desc Status Status Desc
"character" "numeric" "character" "character" "character"
Crm Cd 1 Crm Cd 2 Crm Cd 3 Crm Cd 4 LOCATION
"numeric" "numeric" "numeric" "logical" "character"
Cross Street LAT LON
"character" "numeric" "numeric"
Einlesen der Modus Operandi Codes
mocodes.df.dirty <- read_delim("MO_CODES_Numerical_20191119.txt",
delim = "\\s+",
col_names = c("CodeBeschreibung"),
trim_ws = TRUE
)
mocodes.df <- mocodes.df.dirty %>%
separate(CodeBeschreibung,
into = c("Code", "Beschreibung"),
sep = "(?<=[0-9])\\s+",
extra = "merge"
) %>%
mutate(Code = as.integer(Code))Hinzufügen von Straftat Klassifikation
crmcd.categories <- read_csv("crmcd_categories.csv")Analyse Rohdaten
Modus Operandi:
Der Datensatz enthält eine Spalte mit MoCodes, welche eine Liste an Zahlen enthält. Diese Zahlen sind IDs des Mocodes Datensatzes, welcher den Modus Operandi als Beschreibung enthält.
Format des Datums
Das Datum ist standardmäßig im Format MM/DD/YYYY HH:MM:SS AM/PM angegeben. Jedoch enthalten die Datumsspalten keine Uhrzeit, diese ist, wenn vorhanden, separat angegeben.
Charfälschlicherweise als Datentyp
Die folgenden Datentypen sind fäschlicherweise als Char abgespeichert:
| Spaltenname | Spaltenbeschreibung | Passender Datentyp |
|---|---|---|
| Date Prtd | Meldedatum | Date |
| Date OCC | Verbrechensdatum | Date |
| Time OCC | Verbrechensuhrzeit | Integer |
| Area | Zugeordneter Bereich | Integer |
| Rpt Dist No | Bezirk des Verbrechens | Integer |
| Mocodes | Liste an Modus Operandi Codes | List |
Spalten mit fehlenden Werten (NAs)
In manchen Spalten befinden sich NAs, dazu gehören: - Es existieren NAs in manchen Spalten
- Weapon
- Weapon Descd
- Crime Codes –> nicht alle Taten
Überprüfung Aussagen der Metadaten:
Crm Cd should be the same as Crm Cd 1
Crm Cd 1 sollte die gleichen Werte wie Crm Cd haben:
Crm Cd Indicates the crime committed. (Same as Crime Code 1) Es gibt aber 1956 unterschiedliche Werte –> todo analyse später
Part 1-2 Weg löschen ?!
Area = Area Name ?!
Premise Cd = Premise Desc ?!
Weapon Use Cd = Weapon Desc ?!
3. Transformation & Bearbeitung
Aufbereitung / Umcodierung
# Aufbereitung der Liste mit Codes zur Zuordnung der Modus Operandi
codes_to_numeric <- function(x) {
if (is.na(x)) {
return(NA)
} else {
return(as.numeric(strsplit(x, " ")[[1]]))
}
}
# Transformation der Daten zu sinnvollen Datentypen
crimes.df <- transform(crimes.df.raw,
`Date Rptd` = as.Date(substr(`Date Rptd`, 1, 10), format = "%m/%d/%Y"),
`DATE OCC` = as.Date(substr(`DATE OCC`, 1, 10), format = "%m/%d/%Y"),
`TIME OCC` = as.integer(`TIME OCC`),
`AREA` = as.integer(`AREA`),
`Rpt Dist No` = as.integer(`Rpt Dist No`),
`Crm Cd` = as.integer(`Crm Cd`),
`Mocodes` = lapply(Mocodes, codes_to_numeric)
)crmCd.diff <- which(crimes.df["Crm Cd"] != crimes.df["Crm Cd 1"])
length(crmCd.diff)[1] 1956
# Überprüfen, ob die Spalte nur NAs enthält
if (all(is.na(crimes.df[["Crm Cd 4"]]))) {
crimes.df[["Crm Cd 4"]] <- NULL
}# Löschen von Part 1-2
# Todo Begründung
crimes.df[["Part 1-2"]] <- NULLIn Klassifizierung der Straftaten sind nicht alle Straftaten enthalten
missing_codes <- crimes.df %>%
anti_join(crmcd.categories, by = c("Crm Cd" = "Crm Cd")) %>%
select(`Crm Cd`, `Crm Cd Desc`) %>%
distinct()missing_categories <- read_csv("missing_categories.csv")
# print(missing_categorie, n = nrow(missing_categorie))Join all categories in one table
categories <- rbind(missing_categories, crmcd.categories)
# categories
# categories %>% count(Category)
# unique(categories$Category)rm(missing_codes, codes_to_numeric, missing_categories, crmcd.categories)Joining
- MO & Tabelle
crimes.df.joined <- crimes.df %>%
mutate(`MoCd Desc` = map(Mocodes, ~ mocodes.df$Beschreibung[match(.x, mocodes.df$Code)])) %>%
relocate(`MoCd Desc`, .after = `Mocodes`)
crimes.df.joined %>%
mutate(
codes_str = map_chr(Mocodes, ~ paste(.x, collapse = ", ")),
meanings_str = map_chr(`MoCd Desc`, ~ paste(.x, collapse = ", "))
) %>%
select(DR_NO, codes_str, meanings_str) %>%
head() DR_NO codes_str
1 190326475 NA
2 200106753 1822, 1402, 344
3 200320258 344, 1251
4 200907217 325, 1501
5 220614831 1822, 1501, 930, 2004
6 231808869 1822, 100, 930, 929
meanings_str
1 NA
2 Stranger, Evidence Booked (any crime), Removes vict property
3 Removes vict property, Victim was a student
4 Took merchandise, Other MO (see rpt)
5 Stranger, Other MO (see rpt), Unauthorized use of victim's credit/debit card or number, Suspect is homeless/transient
6 Stranger, Suspect Impersonate, Unauthorized use of victim's credit/debit card or number, Unauthorized use of victim's bank account information
Subsetting
Area
Geschlecht
Abstammung
Art des Crimes
Übersicht des Dataframes
Fazit - Transformation & Bearbeitung
4. Geeignete Visualisierung und Aggregation der Daten
- Welche Klassen von Straftaten werden wie häufig begangen?
- Anzahl Proportional zu Schweregrad
- Viele Diebstahle & andere Straftaten um Geld zu beschaffen
- Welche Stadtteile sind besonders betroffen?
- Ärmere Stadtteile
- Stadtteile mit Gang Gebieten
crimes.tib <- as_tibble(crimes.df)Ortsabhängige Analysen
crimes.df.no_id_theft <- subset(crimes.df, `Crm Cd` != 354)
nrow(crimes.df.no_id_theft)[1] 925352
crimes.df.no_id_theft <- crimes.df.no_id_theft[sample(nrow(crimes.df.no_id_theft), 5000), ]leaflet(crimes.df.no_id_theft) %>%
addTiles() %>% # Standard-OSM-Karte
setView(lng = -118.2437, lat = 34.0522, zoom = 9) %>% # Ansicht auf Los Angeles
addCircleMarkers(~LON, ~LAT,
radius = 5,
color = "blue",
stroke = FALSE,
fillOpacity = 0.8,
popup = ~ paste("ID:", `Crm Cd Desc`)
) # Popup mit der DR_NO IDleaflet(crimes.df) %>%
addTiles() %>% # Grundkarte hinzufügen
setView(lng = -118.2437, lat = 34.0522, zoom = 9) %>%
addHeatmap(
lng = ~LON,
lat = ~LAT,
intensity = nrow(crimes.df),
blur = 20,
max = 0.05,
radius = 10
)